package com.lgj.demo.controller;

import com.lgj.demo.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * redis 操作控制层
 * <a href="https://mp.weixin.qq.com/s/qkuejUUQ-mco-ZX2impZXw">原借鉴地址</a>
 * <a href="https://deepinout.com/redis-cmd/redis-bitmap-cmd/redis-cmd-bitfield.html" >Redis BITFIELD命令</a>
 */
@RestController
@Slf4j
public class RedisController {

    @Autowired
    private SetService setService;
    @Autowired
    private ZSetService zSetService;
    @Autowired
    private UVService uvService;
    @Autowired
    private BigMapService bigMapService;
    @Autowired
    private GEOService geoService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 收藏
     * @return
     */
    @GetMapping("/getRaffle")
    public String getRaffle(){
        log.info("getRaffle ===>>>");
        Integer raffleId = 1;
        setService.join(raffleId, 1000, 1001, 2233, 7890, 44556, 74512);
        setService.luckyFirst(raffleId);
        List lucky = setService.lucky(raffleId, 2);
        log.info("活动：{} 的幸运中奖用户是：{}", raffleId, lucky);
        return "" + lucky.toString();
    }

    /**
     * 点赞
     * @return
     */
    @GetMapping("/getLike")
    public String getLike(){
        log.info("getLike ===>>>");
        long articleId = 100;
        Long likeNum = setService.like(articleId, 1001, 1002, 2001, 3005, 4003);
        setService.unLike(articleId, 2001);
        likeNum = setService.likeNum(articleId);
        boolean b2001 = setService.isLike(articleId, 2001);
        boolean b3005 = setService.isLike(articleId, 3005);
        log.info("文章：{} 点赞数量：{} 用户2001的点赞状态：{} 用户3005的点赞状态：{}", articleId, likeNum, b2001, b3005);
        return "";
    }

    /**
     * 排序
     * @return
     */
    @GetMapping("/getRange")
    public String getRange(){
        log.info("getRange ===>>>");
        zSetService.add(1001, (double) 60);
        zSetService.add(1012, (double) 80);
        zSetService.add(1002, (double) 80);
        zSetService.add(1003, (double) 100);
        zSetService.add(1004, (double) 90);
        zSetService.add(1005, (double) 70);

        // 取所有
        Set<DefaultTypedTuple> range = zSetService.range(0, -1);

        range.stream().forEach((r)->{
            System.out.println(r.getValue() + "/" + r.getScore());
        });

        log.info("所有用户排序：{}", range);
        // 前三名
        range = zSetService.range(0, 2);
        log.info("前三名排序：{}",range);
        return "";
    }

    /**
     * 引用计数 可用于点击页面浏览量技术
     * @return
     */
    @GetMapping("/getIncr")
    public String getIncr(){
        log.info("getIncr ===>>>");
        String key = "incr_add";
        // +1
        redisTemplate.opsForValue().increment(key);
        // 获取值
        Object value = redisTemplate.opsForValue().get(key);
        return "" + value;
    }

    /**
     * 基数统计
     * @return
     */
    @GetMapping("/getUV")
    public Long getUV() {
        log.info("getUV ===>>>");
        Integer pageId = 2;
        for (int i = 0; i < 10000; i++) {
            uvService.uv(pageId, i);
        }
        for (int i = 0; i < 10000; i++) {
            uvService.uv(pageId, i);
        }

        Long uv = uvService.getUv(pageId);
        log.info("pageId:{} uv:{}", pageId, uv);
        return uv;
    }

    /**
     * 测试用户签到
     */
    @GetMapping("/querySignDay")
    public void querySignDay(){
        //模拟用户签到
//        for(int i=5;i<19;i++){
            redisTemplate.opsForValue().setBit("UserId:Sign:560:2022-11", 11, true);
//        }

        System.out.println("560用户今日是否已签到:" + bigMapService.checkSign("560"));
        Map<String, Boolean> stringBooleanMap = bigMapService.querySignedInMonth("560");
        System.out.println("本月签到情况:");
        for (Map.Entry<String, Boolean> entry : stringBooleanMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + (entry.getValue() ? "√" : "-"));
        }
        long countSignedInDayOfMonth = bigMapService.countSignedInDayOfMonth("560");
        System.out.println("本月一共签到:" + countSignedInDayOfMonth + "天");
        System.out.println("目前连续签到:" + bigMapService.queryContinuousSignCount("560", 7) + "天");
    }

    /**
     * 测试地理位置
     */
    @GetMapping("/getGeo")
    public void getGeo(){
        geoService.add("starbucks", new Point(116.62445, 39.86206));
        geoService.add("yidiandian", new Point(117.3514785, 38.7501247));
        geoService.add("xicha", new Point(116.538542, 39.75412));

        geoService.get("starbucks", "yidiandian", "xicha");

        GeoResults nearByXY = geoService.getNearByXY(new Point(116, 39), new Distance(120, Metrics.KILOMETERS));
        List<GeoResult> content = nearByXY.getContent();
        for (GeoResult geoResult : content) {
            log.info("{}", geoResult.getContent());
        }

        GeoResults nearByPlace = geoService.getNearByPlace("starbucks", new Distance(120, Metrics.KILOMETERS));
        content = nearByPlace.getContent();
        for (GeoResult geoResult : content) {
            log.info("{}", geoResult.getContent());
        }

        geoService.getGeoHash("starbucks", "yidiandian", "xicha");

        geoService.del("yidiandian", "xicha");
    }

    /**
     * 发送消息 -> 先进先出队列
     * @return
     */
    @GetMapping("/sendMessageLP")
    public String sendMessageLP(){
        log.info("lp ===>>>");
        String key = "redis:lp:queue";
        long lp = stringRedisTemplate.opsForList().leftPush(key,"lp redis send message!!!");
        return "" + lp;
    }

    /**
     * 发送消息 -> 先进后出队列
     * @return
     */
    @GetMapping("/sendMessageRP")
    public String sendMessageRP(){
        log.info("rp ===>>>");
        String key = "redis:rp:queue";
        long rp = stringRedisTemplate.opsForList().rightPush(key,"rp redis send message!!!");
        return "" + rp;
    }

}
